package com.huyucheng.todolist

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.huyucheng.todolist.utils.executeBackground
import com.huyucheng.todolist.utils.executeMain
import com.huyucheng.todolist.utils.getValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class TodoListViewModel(private val todoDao: TodoDao) : ViewModel() {

    companion object {
        val CHECKED = 1
        val UNCHECKED = 0
    }

    val checkedTodoList: LiveData<ArrayList<Todo>>
        get() = _checkedTodoList
    val uncheckedTodoList: LiveData<ArrayList<Todo>>
        get() = _uncheckedTodoList

    private val _checkedTodoList = MutableLiveData<ArrayList<Todo>>()
    private val _uncheckedTodoList = MutableLiveData<ArrayList<Todo>>()

    init {
        loadTodoListFromDB()
    }

    private fun loadTodoListFromDB() {
        val deferredTodoList  = viewModelScope.async(context = Dispatchers.Default) {
            val todoListFromDB: ArrayList<Todo> =
                getValue { todoDao.loadAllTodos() } as ArrayList<Todo>

            todoListFromDB.sortByDescending { it.priority }
            todoListFromDB
        }

        // BugFix: toList() returns EmptyList when there is no data in database
        viewModelScope.launch(context = Dispatchers.Main) {
            _checkedTodoList.value = (deferredTodoList.await().filter {
                it.checked == CHECKED
            }.toMutableList() as ArrayList<Todo>)
            _uncheckedTodoList.value = (deferredTodoList.await().filter {
                it.checked == UNCHECKED
            }.toMutableList() as ArrayList<Todo>)
        }
    }

    fun deleteTodo(todo: Todo, checkStatus: Int) {
        if (checkStatus == CHECKED) {
            _checkedTodoList.value?.remove(todo)
        } else {
            _uncheckedTodoList.value?.remove(todo)
        }
    }

    fun getTodo(position: Int, checkStatus: Int): Todo? {
        if (checkStatus == CHECKED) {
            return checkedTodoList.value?.get(position)
        } else {
            return uncheckedTodoList.value?.get(position)
        }
    }

    fun getListSize(checkStatus: Int): Int? {
        if (checkStatus == CHECKED) {
            return checkedTodoList.value?.size
        } else {
            return uncheckedTodoList.value?.size
        }
    }

    fun reload() {
        loadTodoListFromDB()
    }

    fun getListByCheckStatus(checkStatus: Int): List<Todo>{
        if (checkStatus == CHECKED) {
            return checkedTodoList.value as List<Todo>
        } else {
            return uncheckedTodoList.value as List<Todo>
        }
    }

    fun addTodo(todo: Todo, checkStatus: Int) {
        if (checkStatus == CHECKED) {
            _checkedTodoList.value?.add(todo)
        } else {
            _uncheckedTodoList.value?.add(todo)
        }
    }
}